﻿/**
 * @file units.cpp
 * @brief 单位转换系统的实现文件
 * @author [WJ]
 * @date [2025/08/08]
 */
#include "libunits\units.h"

#include <fstream>
#include <iostream>
#include <libconfig.h++>
#include <map>
#include <optional>
#include <shared_mutex>
#include <stdexcept>
#include <units/units.hpp>
#include <units/units_conversion_maps.hpp>
#include <unordered_map>
#include <chrono>
#include <vector>
#include <memory>
#include <mutex>

namespace Units {
/**
 * @brief 将错误码转换为可读字符串
 * @param code 错误码
 * @return 对应的错误字符串
 */
const char *errorString(ErrorCode code) {
  switch (code) {
    case ErrorCode::Success:
      return "Success";
    case ErrorCode::InvalidHandle:
      return "Invalid handle";
    case ErrorCode::InvalidParameter:
      return "Invalid parameter";
    case ErrorCode::DimensionNotFound:
      return "Dimension not found";
    case ErrorCode::UnitNotFound:
      return "Unit not found";
    case ErrorCode::ConversionFailed:
      return "Conversion failed";
    case ErrorCode::CustomConversionExists:
      return "Custom conversion already exists";
    case ErrorCode::FileIOError:
      return "File I/O error";
    case ErrorCode::ConfigParseError:
      return "Configuration parsing error";
    case ErrorCode::InvalidUnit:
      return "Invalid unit";
    case ErrorCode::UnknownError:  // 显式处理所有已知枚举
      return "Unknown error";
    case ErrorCode::DefinedUnitsParseError:
      return "Defined units parse error";
    default:  // 防御性处理：应对可能的无效值
      return "Unknown error";
  }
}

// UnitSystem::Private 类实现
/**
 * @class UnitSystem::Private
 * @brief UnitSystem类的私有实现，包含核心业务逻辑
 */
class UnitSystem::Private {
 public:
  /**
   * @brief 构造函数
   * @param logCallback 日志回调函数，默认为nullptr
   */
  explicit Private()
      : logger_(defaultLogCallback) {}

  // 量纲配置结构
  struct DimensionConfig {
    std::string dimension;    // 量纲标识 (长度, 质量等)
    std::string baseUnit;     // 基准单位 (m, kg等)
    std::string currentUnit;  // 当前使用的单位
  };

  // 提取公共逻辑到辅助函数
  auto getOrCreateDimensionConfig(
      const units::precise_unit &defaultUnit) -> DimensionConfig & {
    const auto formatedDimension = units::dimensions(defaultUnit);
    auto it = dimensions_.find(formatedDimension);
    if (it == dimensions_.end()) {
      auto &cfg = dimensions_[formatedDimension] = DimensionConfig();
      cfg.dimension = formatedDimension;
      cfg.baseUnit = cfg.currentUnit = units::to_string(defaultUnit);
      return cfg;
    }
    return it->second;
  }
  /**
   * @brief 设置指定量纲的基准单位
   * @param dimension 量纲名称
   * @param unit 单位名称
   * @return 操作结果码
   */
  ErrorCode setBaseUnit(const std::string &dimension, const std::string &unit);
  /**
   * @brief 设置指定量纲的当前单位
   * @param dimension 量纲名称，用于标识单位的类型（如长度、质量、时间等）
   * @param unit 单位名称
   * @return 返回操作结果，成功返回SUCCESS，失败返回相应的错误码
   */
  ErrorCode setCurrentUnit(const std::string &dimension,
                           const std::string &unit);
  /**
   * @brief 获取指定量纲的基本单位
   * @param dimension 量纲名称
   * @param unit 输出参数，返回该量纲的基本单位
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode getBaseUnit(const std::string &dimension, std::string &unit) const;

  /**
   * @brief 获取指定量纲的当前单位
   * @param dimension 量纲名称
   * @param unit 输出参数，返回该量纲的当前单位
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode getCurrentUnit(const std::string &dimension,
                           std::string &unit) const;

  // 转换相关

  /**
   * @brief 将测量字符串转换为目标单位
   * @param measurement 测量字符串，格式如"10 meter"
   * @param to 目标单位
   * @param result 输出参数，返回转换后的数值
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode convert(const std::string &measurement, const std::string &to,
                    double &result);

  /**
   * @brief 核心转换方法，将值从一个单位转换到另一个单位
   * @param value 要转换的数值
   * @param from 源单位
   * @param to 目标单位
   * @param result 输出参数，返回转换后的数值
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode convert(double value, const std::string &from,
                    const std::string &to, double &result);

  /**
   * @brief 将指定数值转换为基本单位
   * @param value 要转换的数值
   * @param dimension 量纲名称
   * @param result 输出参数，返回转换到基本单位后的数值
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode convertToBase(double value, const std::string &dimension,
                          double &result);

  /**
   * @brief 将基本单位的数值转换为指定量纲的当前单位
   * @param value 基本单位的数值
   * @param dimension 量纲名称
   * @param result 输出参数，返回转换后的数值
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode convertFromBase(double value, const std::string &dimension,
                            double &result);

  /**
   * @brief 注册用户自定义单位
   * @param unitName 自定义单位名称
   * @param definition 单位定义表达式
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode registerUserDefinedUnit(const std::string &unitName,
                                    const std::string &definition);

  // 观察者相关

  /**
   * @brief 注册当前单位变化观察者
   * @param owner 观察者所有者指针，用于标识观察者
   * @param observer 单位变化回调函数
   * @return UnitChangedCallbackAutoDeleter 自动删除器，用于自动注销观察者
   */
  UnitChangedCallbackAutoDeleter registerCurrentUnitChangedObserver(
      void *owner, UnitChangedCallback observer);

  /**
   * @brief 通知当前单位发生变化
   * @param dimension 发生变化的量纲名称
   * @param unit 新的单位名称
   */
  void notifyCurrentUnitChanged(const std::string &dimension,
                                const std::string &unit);

  /**
   * @brief 注册日志回调函数
   * @param logger 日志回调函数指针
   */
  void registerLogger(LogCallback logger);

  /**
   * @brief 记录日志信息
   * @param level 日志级别
   * @param message 日志消息内容
   */
  void log(const std::string &level, const std::string &message) const;

  /**
   * @brief 默认日志回调函数
   * @param level 日志级别
   * @param message 日志消息内容
   */
  static void defaultLogCallback(const std::string &level,
                                 const std::string &message);

  /**
   * @brief 从配置文件加载设置
   * @param filename 配置文件路径
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode loadFromConfigFile(const std::string &filename);

  /**
   * @brief 保存设置到配置文件
   * @param filename 配置文件路径
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode saveToConfigFile(const std::string &filename);

  /**
   * @brief 从文件加载已定义的单位
   * @param filename 单位定义文件路径
   * @return ErrorCode 错误码，成功时返回SUCCESS
   */
  ErrorCode loadDefinedUnitsFromFile(const std::string &filename);

  // 用于保护共享数据的线程同步机制
  // 可共享的互斥锁，用于读写锁机制
  mutable std::shared_mutex mutex_;
  // 可重入互斥锁，用于回调函数的同步访问
  mutable std::recursive_mutex callbackMutex_;
  // 存储维度配置信息的容器
  std::unordered_map<std::string, DimensionConfig> dimensions_;
  // 存储观察者回调函数的容器
  // key为观察者指针，value为当单位改变时需要调用的回调函数
  std::unordered_map<void *, UnitChangedCallback> observers_;
  // 日志回调函数，用于记录系统日志
  LogCallback logger_;
};

// 初始化静态成员
std::unique_ptr<UnitSystem> instance_;
std::once_flag initFlag_;

ErrorCode UnitSystem::Private::setBaseUnit(const std::string &dimension,
                                           const std::string &unit) {
  std::unique_lock<std::shared_mutex> lock(mutex_);

  auto defaultUnit = units::default_unit(dimension);
  if (!units::is_valid(defaultUnit)) {
    return ErrorCode::DimensionNotFound;
  }

  auto baseUnit = units::unit_from_string(unit);
  if (!baseUnit.is_convertible(defaultUnit)) {
    return ErrorCode::ConversionFailed;
  }

  auto &cfg = getOrCreateDimensionConfig(defaultUnit);
  const auto baseString = units::to_string(baseUnit);
  if (cfg.baseUnit != baseString) {
    cfg.baseUnit = baseString;
  }

  if (cfg.currentUnit.empty()) {
    cfg.currentUnit = baseString;
  }

  return ErrorCode::Success;
}

// 设置当前单位
ErrorCode UnitSystem::Private::setCurrentUnit(const std::string &dimension,
                                              const std::string &unit) {
  std::unique_lock<std::shared_mutex> lock(mutex_);

  auto defaultUnit = units::default_unit(dimension);
  if (!units::is_valid(defaultUnit)) {
    return ErrorCode::DimensionNotFound;
  }

  auto newUnit = units::unit_from_string(unit);
  if (!newUnit.is_convertible(defaultUnit)) {
    return ErrorCode::ConversionFailed;
  }

  auto &cfg = getOrCreateDimensionConfig(defaultUnit);
  const auto baseString = units::to_string(newUnit);
  if (cfg.currentUnit != baseString) {
    cfg.currentUnit = baseString;
  }

  lock.unlock();  // 解锁后再通知观察者
  notifyCurrentUnitChanged(dimension, unit);
  return ErrorCode::Success;
}

// 获取基准单位
ErrorCode UnitSystem::Private::getBaseUnit(const std::string &dimension,
                                           std::string &result) const {
  auto defaultUnit = units::default_unit(dimension);
  if (!units::is_valid(defaultUnit)) {
    log("WARNING", std::string("Unknown dimension: ") + dimension);
    return ErrorCode::DimensionNotFound;
  }

  const auto formatedDimension = units::dimensions(defaultUnit);
  {
    std::shared_lock<std::shared_mutex> lock(mutex_);
    if (auto it = dimensions_.find(formatedDimension);
        it != dimensions_.end()) {
      result = it->second.baseUnit;
      return ErrorCode::Success;
    }
  }

  result = units::to_string(defaultUnit);
  return ErrorCode::Success;
}

// 获取当前单位
ErrorCode UnitSystem::Private::getCurrentUnit(const std::string &dimension,
                                              std::string &result) const {
  auto defaultUnit = units::default_unit(dimension);
  if (!units::is_valid(defaultUnit)) {
    log("WARNING", std::string("Unknown dimension: ") + dimension);
    return ErrorCode::DimensionNotFound;
  }

  const auto formatedDimension = units::dimensions(defaultUnit);
  {
    std::shared_lock<std::shared_mutex> lock(mutex_);
    if (auto it = dimensions_.find(formatedDimension);
        it != dimensions_.end()) {
      result = it->second.currentUnit;
      return ErrorCode::Success;
    }
  }

  result = units::to_string(defaultUnit);
  return ErrorCode::Success;
}

ErrorCode UnitSystem::Private::convert(const std::string &measurement,
                                       const std::string &to, double &result) {
  if (measurement.empty() || to.empty()) {
    return ErrorCode::InvalidParameter;
  }

  auto meas = units::measurement_from_string(measurement);
  auto newUnits = to;
  units::precise_unit u2;
  if (to == "*" || newUnits == "<base>") {
    u2 = meas.convert_to_base().units();
    newUnits = units::to_string(u2);
  } else {
    u2 = units::unit_from_string(newUnits);
  }

  if (meas.units().is_convertible(u2)) {
    result = meas.value_as(u2);
    return ErrorCode::Success;
  }

  log("ERROR", "Conversion failed: " + measurement + " to " + to);
  return ErrorCode::ConversionFailed;
}

// 核心转换方法
ErrorCode UnitSystem::Private::convert(double value, const std::string &from,
                                       const std::string &to, double &result) {
  if (from == to) {
    result = value;
    return ErrorCode::Success;
  }

  // 尝试使用LLNL/units进行转换
  auto fromUnit = units::unit_from_string(from);
  auto toUnit = units::unit_from_string(to);
  if (fromUnit.is_convertible(toUnit)) {
    result = units::convert(value, fromUnit, toUnit);
    return ErrorCode::Success;
  }

  const auto errorString =
      "Conversion error : from \"" + from + "\" to \"" + to + "\"";
  log("ERROR", errorString);
  return ErrorCode::ConversionFailed;
}

// 转换为基准单位
ErrorCode UnitSystem::Private::convertToBase(double value,
                                             const std::string &dimension,
                                             double &result) {
  auto defaultUnit = units::default_unit(dimension);
  if (!units::is_valid(defaultUnit)) {
    log("WARNING", std::string("Unknown dimension: ") + dimension);
    return ErrorCode::DimensionNotFound;
  }

  const auto formatedDimension = units::dimensions(defaultUnit);
  {
    std::shared_lock<std::shared_mutex> lock(mutex_);
    if (auto it = dimensions_.find(formatedDimension);
        it != dimensions_.end()) {
      return convert(value, it->second.currentUnit, it->second.baseUnit,
                     result);
    }
  }

  result = value;
  return ErrorCode::Success;
}

// 从基准单位转换
ErrorCode UnitSystem::Private::convertFromBase(double value,
                                               const std::string &dimension,
                                               double &result) {
  auto defaultUnit = units::default_unit(dimension);
  if (!units::is_valid(defaultUnit)) {
    log("WARNING", std::string("Unknown dimension: ") + dimension);
    return ErrorCode::DimensionNotFound;
  }

  const auto formatedDimension = units::dimensions(defaultUnit);
  {
    std::shared_lock<std::shared_mutex> lock(mutex_);
    if (auto it = dimensions_.find(formatedDimension);
        it != dimensions_.end()) {
      return convert(value, it->second.baseUnit, it->second.currentUnit,
                     result);
    }
  }

  result = value;
  return ErrorCode::Success;
}

ErrorCode UnitSystem::Private::registerUserDefinedUnit(
    const std::string &name, const std::string &definition) {
  auto measure = units::measurement_from_string(definition);
  if (!units::is_valid(measure)) return ErrorCode::InvalidUnit;

  units::addUserDefinedInputUnit(name, measure.as_unit());
  return ErrorCode::Success;
}

UnitChangedCallbackAutoDeleter
UnitSystem::Private::registerCurrentUnitChangedObserver(
    void *owner, UnitChangedCallback observer) {
  std::lock_guard<std::recursive_mutex> lock(callbackMutex_);
  observers_[owner] = observer;

  // Create deleter that removes the observer
  auto deleter = std::make_shared<std::function<void()>>([this, owner]() {
    std::lock_guard<std::recursive_mutex> lock(callbackMutex_);
    if (auto it = observers_.find(owner); it != observers_.cend()) {
      observers_.erase(it);
    }
  });

  return deleter;
}

// 通知所有观察者
void UnitSystem::Private::notifyCurrentUnitChanged(
    const std::string &dimension,
    const std::string &unit) {  // 复制回调列表，避免在回调中修改observers_
  std::vector<std::pair<void *, UnitChangedCallback>> observersCopy;
  {
    std::lock_guard<std::recursive_mutex> lock(callbackMutex_);
    for (const auto &[owner, callback] : observers_) {
      observersCopy.emplace_back(owner, callback);
    }
  }

  // 执行回调（不持有锁）
  for (const auto &[owner, observer] : observersCopy) {
    observer(owner, dimension, unit);
  }
}

void UnitSystem::Private::registerLogger(LogCallback logger) {
  std::unique_lock<std::shared_mutex> lock(mutex_);

  if (logger) {
    logger_ = logger;
  } else if (!logger_) {
    logger_ = Private::defaultLogCallback;
  }
}

void UnitSystem::Private::log(const std::string &level,
                              const std::string &message) const {
  std::shared_lock<std::shared_mutex> lock(mutex_);

  if (logger_) {
    logger_(level, message);
  }
}

void UnitSystem::Private::defaultLogCallback(const std::string &level,
                                             const std::string &message) {
  std::cout << "[" << level << "] " << message << std::endl;
}

ErrorCode UnitSystem::Private::loadFromConfigFile(const std::string &filename) {
  libconfig::Config cfg;

  try {
    cfg.readFile(filename.c_str());
  } catch (const libconfig::FileIOException &e) {
    log("ERROR", std::string("Error reading config file: ") + e.what());
    return ErrorCode::FileIOError;
  } catch (const libconfig::ParseException &e) {
    std::string errorString = "Parse error: " + std::string(e.getError()) +
                              " at line " + std::to_string(e.getLine());
    log("ERROR", errorString);
    return ErrorCode::ConfigParseError;
  }

  const auto &root = cfg.getRoot();
  if (!root.exists("units")) {
    log("WARNING", "No units configuration found in file");
    return ErrorCode::ConfigParseError;
  }

  const auto &units = root["units"];

  // 恢复当前单位选择
  if (units.exists("dimensions")) {
    const auto &dimensionsSetting = units["dimensions"];
    // 遍历所有量纲设置
    for (int i = 0; i < dimensionsSetting.getLength(); ++i) {
      const auto &dimSetting = dimensionsSetting[i];

      std::string dimension, baseUnit, currentUnit;
      if (dimSetting.lookupValue("dimension", dimension) &&
          dimSetting.lookupValue("base_unit", baseUnit) &&
          dimSetting.lookupValue("current_unit", currentUnit)) {
        std::unique_lock<std::shared_mutex> lock(mutex_);
        // 插入或更新量纲配置
        dimensions_[dimension] = {
            dimension,   // dimension
            baseUnit,    // baseUnit
            currentUnit  // currentUnit
        };
      }
    }
  }

  log("INFO", "Unit configuration loaded from " + filename);
  return ErrorCode::Success;
}

ErrorCode UnitSystem::Private::saveToConfigFile(const std::string &filename) {
  libconfig::Config cfg;
  auto &root = cfg.getRoot();

  // 创建units组
  auto &units = root.add("units", libconfig::Setting::TypeGroup);

  // 保存量纲配置
  {
    auto &dimensionsSetting =
        units.add("dimensions", libconfig::Setting::TypeList);
    std::shared_lock<std::shared_mutex> lock(mutex_);

    for (const auto &[dimension, config] : dimensions_) {
      auto &dimSetting = dimensionsSetting.add(libconfig::Setting::TypeGroup);
      dimSetting.add("dimension", libconfig::Setting::TypeString) =
          config.dimension;
      dimSetting.add("base_unit", libconfig::Setting::TypeString) =
          config.baseUnit;
      dimSetting.add("current_unit", libconfig::Setting::TypeString) =
          config.currentUnit;
    }
  }

  // 写入文件
  try {
    cfg.writeFile(filename.c_str());
    log("INFO", "Unit configuration saved to " + filename);
    return ErrorCode::Success;
  } catch (const libconfig::FileIOException &e) {
    log("ERROR", "Error writing config file: " + std::string(e.what()));
    return ErrorCode::FileIOError;
  }
}

ErrorCode UnitSystem::Private::loadDefinedUnitsFromFile(
    const std::string &filename) {
  const auto output = units::definedUnitsFromFile(filename);
  if (output.find("unable to read file") != std::string::npos) {
    log("ERROR", "Failed to parse defined units file: " + filename);
    return ErrorCode::FileIOError;
  }
  if (output.empty()) {
    return ErrorCode::Success;
  } else {
    log("INFO", "Custom unit conversion loaded from " + filename);
    return ErrorCode::DefinedUnitsParseError;
  }
}

// UnitSystem 类实现
/**
 * @brief UnitSystem构造函数
 */
UnitSystem::UnitSystem() : d(std::make_unique<Private>()) {}

UnitSystem &UnitSystem::instance() {
  std::call_once(initFlag_, []() { instance_.reset(new UnitSystem()); });
  return *instance_;
}

ErrorCode UnitSystem::convert(const std::string &measurement,
                              const std::string &to, double &result) {
  return d->convert(measurement, to, result);
}
/**
 * @brief Converts a value from one unit to another
 * @param value The value to convert
 * @param from The source unit (e.g. "m", "kg")
 * @param to The target unit (e.g. "cm", "g")
 * @return ConversionResult containing the converted value or error message
 * @throws UnitManagerException if conversion is not possible
 */
ErrorCode UnitSystem::convert(double value, const std::string &from,
                              const std::string &to, double &result) {
  return d->convert(value, from, to, result);
}

ErrorCode UnitSystem::convertToBase(double value, const std::string &dimension,
                                    double &result) {
  return d->convertToBase(value, dimension, result);
}

// 从基准单位转换
ErrorCode UnitSystem::convertFromBase(double value,
                                      const std::string &dimension,
                                      double &result) {
  return d->convertFromBase(value, dimension, result);
}

ErrorCode UnitSystem::setBaseUnit(const std::string &dimension,
                                  const std::string &unit) {
  return d->setBaseUnit(dimension, unit);
}

ErrorCode UnitSystem::setCurrentUnit(const std::string &dimension,
                                     const std::string &unit) {
  return d->setCurrentUnit(dimension, unit);
}

ErrorCode UnitSystem::getBaseUnit(const std::string &dimension,
                                  std::string &result) const {
  return d->getBaseUnit(dimension, result);
}

ErrorCode UnitSystem::getCurrentUnit(const std::string &dimension,
                                     std::string &result) const {
  return d->getCurrentUnit(dimension, result);
}

ErrorCode UnitSystem::registerUserDefinedUnit(const std::string &name,
                                              const std::string &measurement) {
  return d->registerUserDefinedUnit(name, measurement);
}

UnitChangedCallbackAutoDeleter UnitSystem::registerCurrentUnitChangedObserver(
    void *owner, UnitChangedCallback observer) {
  return d->registerCurrentUnitChangedObserver(owner, observer);
}

void UnitSystem::notifyCurrentUnitChanged(const std::string &dimension,
                                          const std::string &newUnit) {
  d->notifyCurrentUnitChanged(dimension, newUnit);
}

void UnitSystem::registerLogger(LogCallback logger) {
  d->registerLogger(logger);
}

ErrorCode UnitSystem::loadFromConfigFile(const std::string &configFile) {
  return d->loadFromConfigFile(configFile);
}

ErrorCode UnitSystem::saveToConfigFile(const std::string &outputFile) {
  return d->saveToConfigFile(outputFile);
}

ErrorCode UnitSystem::loadDefinedUnitsFromFile(const std::string &filename) {
  return d->loadDefinedUnitsFromFile(filename);
}

void saveDefinedUnitsToFile(const std::string &filename) {
  std::ofstream file(filename);
  if (!file.is_open()) {
    std::cerr << "Error opening file: " << filename << std::endl;
    return;
  }

  file << R"(
# comment1
meeter == meter
meh == meeter per hour
# => indicates input only unit
     mehmeh => meh/s
# <= indicates output only unit
     hemhem => s/meh

# comment2
yodles=73 counts

# comment
"yeedles", 19 yodles

yimdles; dozen yeedles

# test the quotes for inclusion
"bl==p"=18.7 cups

# test single quotes for inclusion
'y,,p',9 tons

# ignore just one quote
'np==14 kg

# escaped quotes
"j\"\""= 13.5 W

# escaped quotes
'q""'= 15.5 W
            )";

  if (file.fail()) {
    std::cerr << "Error writing to file: " << filename << std::endl;
  }
  file.close();
}

void testUnitSystem() {
  // 设置日志回调
  static auto logger = [](const std::string &level, const std::string &msg) {
    std::cout << "[TEST LOG][" << level << "] " << msg << std::endl;
  };

  UnitSystem manager;

  manager.registerLogger(logger);

  // 1. 测试基本长度单位转换
  auto lengthTest = [&manager]() {
    manager.setCurrentUnit("length", "m");

    // 米到厘米
    auto m_to_cm = 0.0;
    manager.convert(1.5, "m", "cm", m_to_cm);
    if (std::abs(m_to_cm - 150) > 1e-6) {
      logger("ERROR", "1.5 m to cm conversion failed");
    }

    // 千米到米
    auto km_to_m = 0.0;
    manager.convert(2.3, "km", "m", km_to_m);
    if (std::abs(km_to_m - 2300) > 1e-6) {
      logger("ERROR", "2.3 km to m conversion failed");
    }

    // 反向转换
    auto cm_to_m = 0.0;
    manager.convert(250, "cm", "m", cm_to_m);
    if (std::abs(cm_to_m - 2.5) > 1e-6) {
      logger("ERROR", "250 cm to m conversion failed");
    }
  };

  // 2. 测试质量单位转换
  auto massTest = [&manager]() {
    manager.setCurrentUnit("mass", "kg");

    // 千克到克
    auto kg_to_g = 0.0;
    manager.convert(0.75, "kg", "g", kg_to_g);
    if (std::abs(kg_to_g - 750) > 1e-6) {
      logger("ERROR", "0.75 kg to g conversion failed");
    }

    // 公吨tonne到千克
    auto t_to_kg = 0.0;
    manager.convert(1.2, "t", "kg", t_to_kg);
    if (std::abs(t_to_kg - 1200) > 1e-6) {
      logger("ERROR", "1.2 t to kg conversion failed");
    }

    // 美吨(短吨)到千克
    auto ton_to_kg = 0.0;
    manager.convert(1.2, "ton", "kg", ton_to_kg);
    if (std::abs(ton_to_kg - 1088.6216879999999) > 1e-6) {
      logger("ERROR", "1.2 ton to kg conversion failed");
    }
  };

  // 3. 测试压力单位转换
  auto pressureTest = [&manager]() {
    manager.setCurrentUnit("pressure", "Pa");

    // 帕到千帕
    auto pa_to_kpa = 0.0;
    manager.convert(1500, "Pa", "kPa", pa_to_kpa);
    if (std::abs(pa_to_kpa - 1.5) > 1e-6) {
      logger("ERROR", "1500 Pa to kPa conversion failed");
    }

    // 巴到帕
    auto bar_to_pa = 0.0;
    manager.convert(2.5, "bar", "Pa", bar_to_pa);
    if (std::abs(bar_to_pa - 250000) > 1e-6) {
      logger("ERROR", "2.5 bar to Pa conversion failed");
    }

    // 反向转换
    auto pa_to_bar = 0.0;
    manager.convert(100000, "Pa", "bar", pa_to_bar);
    if (std::abs(pa_to_bar - 1.0) > 1e-6) {
      logger("ERROR", "100000 Pa to bar conversion failed");
    }
  };

  // 5. 测试扭矩单位转换
  auto torqueTest = [&manager]() {
    manager.setCurrentUnit("torque", "N.m");

    // 牛米到千克力米
    manager.registerUserDefinedUnit("N.m", "kgf.m * 0.101971621");
    auto nm_to_kgfm = 0.0;
    manager.convert(10, "N.m", "kgf.m", nm_to_kgfm);
    if (std::abs(nm_to_kgfm - 1.01971621) > 1e-6) {
      logger("ERROR", "10 N.m to kgf.m conversion failed");
    }

    // 反向转换
    auto kgfm_to_nm = 0.0;
    manager.convert(5, "kgf.m", "N.m", kgfm_to_nm);
    if (std::abs(kgfm_to_nm - 49.03325) > 1e-2) {
      logger("ERROR", "5 kgf.m to N.m conversion failed");
    }
  };

  // 6. 测试流量单位转换
  auto flowTest = [&manager]() {
    manager.setCurrentUnit("flow", "m3/s");

    // 立方米/秒到升/分钟
    auto m3s_to_lmin = 0.0;
    manager.convert(0.001, "m3/s", "l/min", m3s_to_lmin);
    if (std::abs(m3s_to_lmin - 60) > 1e-6) {
      logger("ERROR", "0.001 m3/s to l/min conversion failed");
    }

    // 加仑/分钟到立方米/秒
    manager.registerUserDefinedUnit("gal/min", "m3/s * 6.30901964e-5");
    auto gpm_to_m3s = 0.0;
    manager.convert(100, "gal/min", "m3/s", gpm_to_m3s);
    if (std::abs(gpm_to_m3s - 0.00630901964) > 1e-8) {
      logger("ERROR", "100 gal/min to m3/s conversion failed");
    }
  };

  // 7. 测试性能（大量转换）
  auto performanceTest = [&manager]() {
    const int iterations = 100000;
    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < iterations; ++i) {
      double result = 0.0;
      manager.convert(i % 100, "m", "cm", result);
    }

    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
                        std::chrono::high_resolution_clock::now() - start)
                        .count();

    logger("INFO", "Performance test: " + std::to_string(iterations) +
                       " conversions took " + std::to_string(duration) + " ms");
  };

  // 8. 测试错误情况
  auto errorTest = [&manager]() {
    // 无效单位
    auto invalid = 0.0;
    auto resultCode = manager.convert(10, "invalid", "m", invalid);
    if (resultCode != ErrorCode::Success) {
      logger("INFO",
             "10 invalid to m conversion failed (Invalid unit conversion "
             "should have failed)");
    }

    // 不兼容的单位
    auto incompatible = 0.0;
    resultCode = manager.convert(10, "kg", "m", incompatible);
    if (resultCode != ErrorCode::Success) {
      logger("INFO",
             "10 kg to m conversion failed (Incompatible unit conversion "
             "should have failed)");
    }
  };

  // 9. 测试温度单位转换
  auto temperatureTest = [&manager]() {
    manager.setCurrentUnit("temperature", "°C");  // 设置当前单位为摄氏度

    // 测试1: 摄氏度转华氏度 (0°C = 32°F)
    auto c_to_f = 0.0;
    manager.convert(0.0, u8"°C", u8"°F", c_to_f);
    if (std::abs(c_to_f - 32.0) > 1e-6) {
      logger("ERROR", "0°C to °F conversion failed. Expected 32.0, got " +
                          std::to_string(c_to_f));
    }

    // 测试2: 华氏度转摄氏度 (100°F ≈ 37.7778°C)
    auto f_to_c = 0.0;
    manager.convert(100.0, u8"°F", u8"°C", f_to_c);
    if (std::abs(f_to_c - 37.777777) > 1e-6) {  // 100°F = (100-32)/1.8
      logger("ERROR", "100°F to °C conversion failed. Expected ~37.777, got " +
                          std::to_string(f_to_c));
    }

    // 测试3: 摄氏度转开尔文 (-273.15°C = 0K，绝对零度)
    auto c_to_k = 0.0;
    manager.convert(-273.15, u8"°C", u8"K", c_to_k);
    if (std::abs(c_to_k - 0.0) > 1e-6) {
      logger("ERROR", "Absolute zero (-273.15°C) to K conversion failed");
    }

    // 测试4: 反向转换（开尔文转摄氏度）
    auto k_to_c = 0.0;
    manager.convert(300.0, u8"K", u8"°C", k_to_c);
    if (std::abs(k_to_c - 26.85) > 1e-6) {  // 300K = 26.85°C
      logger("ERROR", "300K to °C conversion failed. Expected 26.85, got " +
                          std::to_string(k_to_c));
    }

    // 测试5: 边界值（沸点100°C转华氏度）
    auto boil_c_to_f = 0.0;
    manager.convert(100.0, u8"°C", u8"°F", boil_c_to_f);
    if (std::abs(boil_c_to_f - 212.0) > 1e-6) {
      logger("ERROR", "100°C (boiling) to °F conversion failed");
    }
  };

  auto loadDefinitions = [&manager]() {
    {
      auto counts = 0.0;
      auto resultCode = manager.convert(10, "yodles", "counts", counts);
      if (resultCode != ErrorCode::Success) {
        logger("INFO",
               "10 yodles to yodles conversion failed (Invalid unit conversion "
               "should have failed)");
      }
    }

    try {
      saveDefinedUnitsToFile("defined_units.def");
    } catch (const std::exception &e) {
      logger("ERROR",
             std::string("Save defined units to file error: ") + e.what());
    }
    // 加载定义文件
    manager.loadDefinedUnitsFromFile("defined_units.def");

    {
      auto value = 0.0;
      manager.convert(10, "meeter", "cm", value);
      if (std::abs(value - 1000) > 1e-6) {
        logger("ERROR", "10 meeter to cm conversion failed");
      }
    }

    {
      auto counts = 0.0;
      manager.convert(10, "yodles", "counts", counts);
      if (std::abs(counts - 730) > 1e-6) {
        logger("ERROR", "10 yodles to counts conversion failed");
      }
    }

    {
      auto counts = 0.0;
      manager.convert(10, "yeedles", "yodles", counts);
      if (std::abs(counts - 190) > 1e-6) {
        logger("ERROR", "10 yeedles to yodles conversion failed");
      }
    }

    {
      auto counts = 0.0;
      manager.convert(10, "yeedles", "counts", counts);
      if (std::abs(counts - 13870) > 1e-6) {
        logger("ERROR", "10 yeedles to counts conversion failed");
      }
    }

    {
      auto cups = 0.0;
      manager.convert(10, "bl==p", "cups", cups);
      if (std::abs(cups - 187) > 1e-6) {
        logger("ERROR", "10 \"bl==p\" to cups conversion failed");
      }
    }

    {
      auto tons = 0.0;
      manager.convert(10, "y,,p", "tons", tons);
      if (std::abs(tons - 90) > 1e-6) {
        logger("ERROR", "10 \"y,,p\" to tons conversion failed");
      }
      manager.convert(10, "y,,p", "kg", tons);
      if (std::abs(tons - 90 * units::unit_from_string("tons").multiplier()) >
          1e-6) {
        logger("ERROR", "10 \"y,,p\" to kg conversion failed");
      }
    }

    {
      auto kg = 0.0;
      manager.convert(10, "np", "kg", kg);
      if (std::abs(kg - 140) > 1e-6) {
        // np 转换报错，是因为n 被认为是一个前缀
        logger("ERROR", "10 \"np=\" to kg conversion failed, kg = " +
                            std::to_string(kg));
      }
    }
    {
      auto cups = 0.0;
      manager.convert(10, "j\"\"", "W", cups);
      if (std::abs(cups - 135) > 1e-6) {
        logger("ERROR", "10 \"j\"\"\" to W conversion failed");
      }
    }
  };

  // 运行所有测试
  lengthTest();
  massTest();
  pressureTest();
  torqueTest();
  flowTest();
  // performanceTest();
  temperatureTest();
  errorTest();
  loadDefinitions();

  logger("INFO", "All tests completed");

  {
    units::precise_unit a = units::unit_from_string("0.5bar");
    units::addUserDefinedInputUnit("mybar", a);

    auto value = 0.0;
    manager.convert(100, "bar", "mybar", value);
    if (std::abs(value - 200.0) > 1e-8) {
      logger("ERROR", "100 bar to hfbar conversion failed");
    }
  }
  {
    units::precise_unit a = units::unit_from_string("0.5bar");
    units::addUserDefinedInputUnit("mybar", a);

    auto value = 0.0;
    manager.convert(100, "bar", "mybar", value);
    if (std::abs(value - 200.0) > 1e-8) {
      logger("ERROR", "100 bar to hfbar conversion failed");
    }
  }
}

void testUnitSystemSerialization() {
  try {
    Units::UnitSystem &unitSystem = Units::UnitSystem::instance();

    // 使用单位系统...
    auto result = 0.0;
    unitSystem.convert(100, "km", "mi", result);
    std::cout << "100 km = " << result << " mi" << std::endl;

    unitSystem.registerUserDefinedUnit("N.m", "kgf.m * 0.101971621");
    unitSystem.registerUserDefinedUnit("gal/min", "m3/s * 6.30901964e-5 ");

    // 修改配置后保存
    unitSystem.setCurrentUnit("length", "mm");
    { unitSystem.saveToConfigFile("units_modified_1.cfg"); }

    // 从文件加载配置
    {
      unitSystem.saveToConfigFile("units_modified_2.cfg");
      unitSystem.loadFromConfigFile("units_modified_1.cfg");
    }
  } catch (const std::exception &e) {
    std::cerr << "Error: " << e.what() << std::endl;
    return;
  }
}
}  // namespace Units
